#include "SystemScheduler.h"

#include <QDebug>

#include "ConfigManager.h"
#include "DeviceManager.h"
#include "SystemConfig.h"
#include "TaskStateMachine.h"
#include "Upload.h"
#include "database.h"

// SystemInfo序列化方法实现
QJsonObject SystemInfo::toJson() const
{
    QJsonObject json;
    json["nextAnalysisTime"] =
        nextAnalysisTime.isValid() ? nextAnalysisTime.toString(Qt::ISODate) : QString();
    json["nextZeroCheckTime"] =
        nextZeroCheckTime.isValid() ? nextZeroCheckTime.toString(Qt::ISODate) : QString();
    json["nextStdCheckTime"] =
        nextStdCheckTime.isValid() ? nextStdCheckTime.toString(Qt::ISODate) : QString();
    json["nextCalibTime"] =
        nextCalibTime.isValid() ? nextCalibTime.toString(Qt::ISODate) : QString();
    json["nextSpikeRecoveryTime"] =
        nextSpikeRecoveryTime.isValid() ? nextSpikeRecoveryTime.toString(Qt::ISODate) : QString();
    json["nextCleanTime"] =
        nextCleanTime.isValid() ? nextCleanTime.toString(Qt::ISODate) : QString();
    return json;
}

void SystemInfo::fromJson(const QJsonObject& json)
{
    QString timeStr;

    timeStr = json["nextAnalysisTime"].toString();
    nextAnalysisTime =
        timeStr.isEmpty() ? QDateTime() : QDateTime::fromString(timeStr, Qt::ISODate);

    timeStr = json["nextZeroCheckTime"].toString();
    nextZeroCheckTime =
        timeStr.isEmpty() ? QDateTime() : QDateTime::fromString(timeStr, Qt::ISODate);

    timeStr = json["nextStdCheckTime"].toString();
    nextStdCheckTime =
        timeStr.isEmpty() ? QDateTime() : QDateTime::fromString(timeStr, Qt::ISODate);

    timeStr = json["nextCalibTime"].toString();
    nextCalibTime = timeStr.isEmpty() ? QDateTime() : QDateTime::fromString(timeStr, Qt::ISODate);

    timeStr = json["nextSpikeRecoveryTime"].toString();
    nextSpikeRecoveryTime =
        timeStr.isEmpty() ? QDateTime() : QDateTime::fromString(timeStr, Qt::ISODate);

    timeStr = json["nextCleanTime"].toString();
    nextCleanTime = timeStr.isEmpty() ? QDateTime() : QDateTime::fromString(timeStr, Qt::ISODate);
}

SystemScheduler::SystemScheduler(QObject* parent) : QObject(parent)
{
    m_timer = new QTimer(this);
    connect(m_timer, &QTimer::timeout, this, &SystemScheduler::checkScheduled);
    m_timer->setInterval(1000);
    m_taskTimer = new QTimer(this);
    connect(m_taskTimer, &QTimer::timeout, this, &SystemScheduler::onTaskTimer);
    m_taskTimer->setInterval(5000);

    // 初始化任务状态机
    m_taskStateMachine = new TaskStateMachine(this);
    m_taskStateMachine->start();
    connect(m_taskStateMachine, &TaskStateMachine::taskStarted, this,
            [this](int taskCode, const QString& taskName) { emit currentTaskChanged(taskCode); });
    connect(m_taskStateMachine, &TaskStateMachine::taskFinished, this, [this](int taskCode) {
        emit currentTaskChanged(static_cast<qint16>(AtomicOperation::IDLE));
    });
    connect(m_taskStateMachine, &TaskStateMachine::taskFailed, this,
            [this](int taskCode, const QString& reason) {
                qDebug() << "任务失败" << taskCode << "原因:" << reason;
                emit taskFailed(static_cast<qint16>(taskCode), reason);
            });
    connect(m_taskStateMachine, &TaskStateMachine::taskCompleted, this, [this](int taskCode) {
        qDebug() << "任务完成" << taskCode;
        emit taskCompleted(taskCode);
    });

    // 初始化当前配置
    m_currentConfig = SystemConfigManager::instance()->getConfig();

    // 加载SystemInfo，如果加载失败或有过期时间则重新计算
    if (!loadSystemInfo()) {
        qDebug() << "SystemInfo加载失败，重新计算所有时间";
        calculateNextTime(m_currentConfig);
    } else {
        // 验证并更新过期的时间（只更新过期的）
        updateExpiredTimes(m_currentConfig);
    }
}

SystemScheduler::~SystemScheduler()
{
    if (m_timer) {
        m_timer->stop();
    }
}

void SystemScheduler::start()
{
    qDebug() << "系统调度器启动...";
    m_isRunning = true;

    // 启动前先更新任务时间（确保时间是最新的）
    updateExpiredTimes(m_currentConfig);

    m_timer->start();
    // 开启设备数据获取
    auto deviceManager = DeviceManager::instance();
    deviceManager->startAllDataMonitoring();
    Upload::Upload::instance()->start();  // 启动数据上传
    emit isRunningChanged(m_isRunning);
}

void SystemScheduler::stop()
{
    qDebug() << "系统调度器停止";
    m_isRunning = false;
    m_timer->stop();
    Upload::Upload::instance()->stop();  // 停止数据上传
    m_taskStateMachine->stopCurrentTask();
    emit isRunningChanged(m_isRunning);
}

void SystemScheduler::updateNextTimes(const SystemConfig& config)
{
    m_currentConfig = config;
    calculateNextTime(m_currentConfig);
}

void SystemScheduler::executeTask(qint16 operateCode)
{
    qDebug() << "准备执行任务:" << getTaskName(operateCode);

    // 使用TaskStateMachine执行任务
    if (m_taskStateMachine->hasCompositeTask(operateCode)) {
        // 执行复合任务
        if (m_taskStateMachine->executeTask(operateCode)) {
            m_currentTaskCode = operateCode;
            emit taskExecuted(operateCode);
        } else {
            qDebug() << "复合任务执行失败";
        }
    } else {
        // 执行单步操作
        // 将SystemTask枚举转换为AtomicOperation
        AtomicOperation atomicOp = static_cast<AtomicOperation>(operateCode);
        if (m_taskStateMachine->executeAtomicOperation(atomicOp)) {
            m_currentTaskCode = operateCode;
            emit taskExecuted(operateCode);
            emit currentTaskChanged(operateCode);
            m_taskTimer->start();
        } else {
            qDebug() << "单步任务执行失败";
        }
    }
    updateExpiredTimes(m_currentConfig);
}

void SystemScheduler::setTaskCondition(const QString& key, bool value)
{
    if (m_taskStateMachine) {
        m_taskStateMachine->setCondition(key, value);
    }
}

void SystemScheduler::checkScheduled()
{
    if (!m_isRunning) return;

    QDateTime currentDateTime = QDateTime::currentDateTime();
    int currentHour = currentDateTime.time().hour();
    int currentMinute = currentDateTime.time().minute();

    // 使用静态变量记录上次执行的小时，确保每小时只执行一次
    static int lastExecutedHour = -1;

    if (currentMinute == 0 && currentHour != lastExecutedHour) {
        hourHandler(currentDateTime);
        insertHourlyData();
        lastExecutedHour = currentHour;  // 记录已执行的小时
    }
}

void SystemScheduler::hourHandler(QDateTime currentDateTime)
{
    int currentHour = currentDateTime.time().hour();
    QDateTime currentTime = QDateTime(currentDateTime.date(), QTime(currentHour, 0, 0));

    if (0) {
    } else if (currentTime == m_info.nextSpikeRecoveryTime) {
        qDebug() << "当前时间" << currentDateTime.toString("yyyy-MM-dd HH:mm:ss") << "符合加标回收";
        executeTask(COMPOSITE_TASK_SPIKE_RECOVERY);
    } else if (currentTime == m_info.nextCalibTime) {
        qDebug() << "当前时间" << currentDateTime.toString("yyyy-MM-dd HH:mm:ss") << "符合校准";
        executeTask(static_cast<qint16>(AtomicOperation::CALIB_FULL));
    } else if (currentTime == m_info.nextZeroCheckTime) {
        qDebug() << "当前时间" << currentDateTime.toString("yyyy-MM-dd HH:mm:ss") << "符合零点核查";
        executeTask(static_cast<qint16>(AtomicOperation::ZERO_CHECK));
    } else if (currentTime == m_info.nextStdCheckTime) {
        qDebug() << "当前时间" << currentDateTime.toString("yyyy-MM-dd HH:mm:ss") << "符合标样核查";
        executeTask(static_cast<qint16>(AtomicOperation::STD_CHECK));
    } else if (currentTime == m_info.nextCleanTime) {
        qDebug() << "当前时间" << currentDateTime.toString("yyyy-MM-dd HH:mm:ss") << "符合清洗";
        executeTask(static_cast<qint16>(AtomicOperation::CLEAN));
    } else if (currentTime == m_info.nextAnalysisTime) {
        qDebug() << "当前时间" << currentDateTime.toString("yyyy-MM-dd HH:mm:ss") << "符合定时分析";
        executeTask(COMPOSITE_TASK_ANALYSIS);
    }
}

void SystemScheduler::calculateNextTime(const SystemConfig& config)
{
    QDateTime currentDateTime = QDateTime::currentDateTime();
    int currentHour = currentDateTime.time().hour();

    // 水样测量 - 使用专门的函数
    m_info.nextAnalysisTime = calculateAnalysisTime(config);
    // 使用通用函数计算基于间隔的时间
    m_info.nextZeroCheckTime =
        calculateIntervalBasedTime(config.zeroCheckIntervalDays, config.zeroCheckTime);
    m_info.nextStdCheckTime =
        calculateIntervalBasedTime(config.stdCheckIntervalDays, config.stdCheckTime);
    m_info.nextCalibTime = calculateIntervalBasedTime(config.calibIntervalDays, config.calibTime);
    m_info.nextSpikeRecoveryTime =
        calculateIntervalBasedTime(config.spikeRecoveryIntervalDays, config.spikeRecoveryTime);
    m_info.nextCleanTime = calculateIntervalBasedTime(config.cleanIntervalDays, config.cleanTime);

    // 自动保存SystemInfo
    saveSystemInfo();
    emit infoChanged(m_info);
}

void SystemScheduler::insertHourlyData()
{
    // 插入整点数据
    QDateTime currentDateTime = QDateTime::currentDateTime();
    DeviceManager* deviceManager = DeviceManager::instance();
    QMap<QString, double> deviceValues;
    for (const QString& name : DEVICE_NAMES) {
        auto helper = deviceManager->getDeviceHelper(name);
        if (helper && DEVICE_MAP[name].isShowData && helper->isEnabled()) {
            deviceValues[name] = helper->getDeviceData().analyze_lastResult;
        }
    }
    Database::insertHourlyData(currentDateTime, deviceValues);
}

void SystemScheduler::onTaskTimer()
{
    // 如果有任务在执行，跳过检查
    if (m_taskStateMachine->getCurrentStepIndex() >= 0) {
        return;
    }

    auto deviceManager = DeviceManager::instance();
    bool isAllIdle = true;
    for (const QString& name : DEVICE_NAMES) {
        auto helper = deviceManager->getDeviceHelper(name);
        if (helper && helper->isEnabled()) {
            // 判断所有设备是否都空闲
            isAllIdle &= helper->isIdle();
        }
    }
    if (isAllIdle) {
        // 只停止定时器，不再发射信号（TaskStateMachine已经发射过了）
        m_taskTimer->stop();
    }
}

bool SystemScheduler::loadSystemInfo()
{
    ConfigManager* configManager = ConfigManager::instance();
    configManager->loadConfig();

    if (!configManager->hasSection("system_info")) {
        qDebug() << "SystemInfo配置节不存在";
        return false;
    }

    QJsonObject jsonObject = configManager->getSection("system_info");
    m_info.fromJson(jsonObject);

    qDebug() << "SystemInfo加载成功";
    return true;
}

bool SystemScheduler::saveSystemInfo()
{
    ConfigManager* configManager = ConfigManager::instance();
    QJsonObject jsonObject = m_info.toJson();

    configManager->setSection("system_info", jsonObject);
    bool result = configManager->saveConfig();

    if (result) {
        qDebug() << "SystemInfo保存成功";
    } else {
        qDebug() << "SystemInfo保存失败";
    }

    return result;
}

QString SystemScheduler::getTaskName(qint16 operateCode) const
{
    // 复合任务
    if (operateCode == COMPOSITE_TASK_SPIKE_RECOVERY) {
        return "加标回收";
    } else if (operateCode == COMPOSITE_TASK_ANALYSIS) {
        return "水样测量";
    }

    // 原子操作
    AtomicOperation op = static_cast<AtomicOperation>(operateCode);
    return TaskStateMachine::getOperationName(op);
}

void SystemScheduler::updateExpiredTimes(const SystemConfig& config)
{
    QDateTime currentDateTime = QDateTime::currentDateTime();
    bool needSave = false;

    qDebug() << "验证SystemInfo中的时间，当前时间:"
             << currentDateTime.toString("yyyy-MM-dd HH:mm:ss");

    // 检查每个时间字段，只重新计算过期的
    if (m_info.nextAnalysisTime.isValid() && m_info.nextAnalysisTime <= currentDateTime) {
        qDebug() << "水样测量时间已过期，重新计算此项";
        m_info.nextAnalysisTime = calculateAnalysisTime(config);
        needSave = true;
    }

    if (m_info.nextZeroCheckTime.isValid() && m_info.nextZeroCheckTime <= currentDateTime) {
        qDebug() << "零点核查时间已过期，重新计算此项";
        m_info.nextZeroCheckTime =
            calculateIntervalBasedTime(config.zeroCheckIntervalDays, config.zeroCheckTime);
        needSave = true;
    }

    if (m_info.nextStdCheckTime.isValid() && m_info.nextStdCheckTime <= currentDateTime) {
        qDebug() << "标液核查时间已过期，重新计算此项";
        m_info.nextStdCheckTime =
            calculateIntervalBasedTime(config.stdCheckIntervalDays, config.stdCheckTime);
        needSave = true;
    }

    if (m_info.nextCalibTime.isValid() && m_info.nextCalibTime <= currentDateTime) {
        qDebug() << "校正标定时间已过期，重新计算此项";
        m_info.nextCalibTime =
            calculateIntervalBasedTime(config.calibIntervalDays, config.calibTime);
        needSave = true;
    }

    if (m_info.nextSpikeRecoveryTime.isValid() && m_info.nextSpikeRecoveryTime <= currentDateTime) {
        qDebug() << "加标回收时间已过期，重新计算此项";
        m_info.nextSpikeRecoveryTime =
            calculateIntervalBasedTime(config.spikeRecoveryIntervalDays, config.spikeRecoveryTime);
        needSave = true;
    }

    if (m_info.nextCleanTime.isValid() && m_info.nextCleanTime <= currentDateTime) {
        qDebug() << "清洗时间已过期，重新计算此项";
        m_info.nextCleanTime =
            calculateIntervalBasedTime(config.cleanIntervalDays, config.cleanTime);
        needSave = true;
    }

    if (needSave) {
        qDebug() << "检测到过期时间，已重新计算并保存";
        saveSystemInfo();
    } else {
        qDebug() << "所有时间均有效，无需重新计算";
    }

    emit infoChanged(m_info);
}

QDateTime SystemScheduler::calculateAnalysisTime(const SystemConfig& config) const
{
    // 水样测量时间计算 - 处理多个时间点的位掩码逻辑
    QDateTime currentDateTime = QDateTime::currentDateTime();
    int currentHour = currentDateTime.time().hour();

    if (config.scheduled == 0) {
        // 如果没有设置任何测量时间，返回无效时间
        return QDateTime();
    } else {
        // 查找今天剩余时间内最早的测量时间
        int nextHour = -1;
        for (int hour = currentHour + 1; hour < 24 && nextHour == -1; hour++) {
            if (SystemConfigManager::instance()->isScheduled(hour)) {
                nextHour = hour;
            }
        }

        if (nextHour != -1) {
            // 今天还有安排的测量时间
            return QDateTime(currentDateTime.date(), QTime(nextHour, 0));
        } else {
            // 查找明天最早的测量时间
            for (int hour = 0; hour < 24 && nextHour == -1; hour++) {
                if (SystemConfigManager::instance()->isScheduled(hour)) {
                    nextHour = hour;
                }
            }
            return QDateTime(currentDateTime.date().addDays(1), QTime(nextHour, 0));
        }
    }
}

QDateTime SystemScheduler::calculateIntervalBasedTime(int intervalDays, int timeHour) const
{
    if (intervalDays == 0) {
        return QDateTime();  // 未启用，返回无效时间
    }

    QDateTime currentDateTime = QDateTime::currentDateTime();
    int currentHour = currentDateTime.time().hour();

    if (currentHour < timeHour) {
        // 当前小时小于设置小时，从今天开始算
        return QDateTime(currentDateTime.date(), QTime(timeHour, 0));
    } else {
        // 当前小时大于等于设置小时，从下一周期开始算
        return QDateTime(currentDateTime.date().addDays(intervalDays), QTime(timeHour, 0));
    }
}
